package edu.ynu.se.xiecheng.service;

import edu.ynu.se.xiecheng.entity.CameraRecord;
import edu.ynu.se.xiecheng.entity.Device;
import edu.ynu.se.xiecheng.entity.SoilData;
import edu.ynu.se.xiecheng.dto.DeviceDTO;
import edu.ynu.se.xiecheng.dto.SensorDataDTO;
import edu.ynu.se.xiecheng.dto.ChartDataDTO;
import edu.ynu.se.xiecheng.repository.CameraRecordRepository;
import edu.ynu.se.xiecheng.repository.DeviceRepository;
import edu.ynu.se.xiecheng.repository.SoilDataRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.Collections;
import java.time.format.DateTimeFormatter;
import java.util.Optional;
import java.math.BigDecimal;

/**
 * 设备服务类
 */
@Service
public class DeviceService {
    @Autowired
    private DeviceRepository deviceRepository;

    @Autowired
    private SoilDataRepository soilDataRepository;

    @Autowired
    private CameraRecordRepository cameraRecordRepository;

    /**
     * 根据大棚ID查询设备列表
     */
    public List<DeviceDTO> findByGreenhouseId(Long greenhouseId) {
        return deviceRepository.findByGreenhouseId(greenhouseId).stream()
            .map(this::convertToDTO)
            .collect(Collectors.toList());
    }

    /**
     * 根据大棚ID和设备类型查询设备列表
     */
    public List<DeviceDTO> findByDeviceTypeAndGreenhouseId(Long deviceTypeId, Long greenhouseId) {
        return deviceRepository.findByDeviceTypeIdAndGreenhouseId(deviceTypeId, greenhouseId).stream()
            .map(this::convertToDTO)
            .collect(Collectors.toList());
    }

    /**
     * 根据设备类型查询设备列表
     */
    public List<DeviceDTO> findByDeviceType(Long deviceTypeId) {
        return deviceRepository.findByDeviceTypeId(deviceTypeId).stream()
            .map(this::convertToDTO)
            .collect(Collectors.toList());
    }

    /**
     * 获取设备的最新传感器数据
     */
    public SensorDataDTO getSensorData(Long deviceId) {
        List<SoilData> dataList = soilDataRepository.findByDeviceIdOrderByCollectTimeDesc(deviceId);
        return dataList.isEmpty() ? null : convertToSensorDTO(dataList.get(0), deviceId);
    }

    /**
     * 获取摄像头历史记录
     */
    public List<CameraRecord> getCameraRecords(Long deviceId) {
        return cameraRecordRepository.findByDeviceIdOrderByRecordTimeDesc(deviceId);
    }

    /**
     * 获取设备历史数据
     */
    public List<SensorDataDTO> getDeviceHistory(Long deviceId, String timeRange, Integer limit) {
        LocalDateTime endTime = LocalDateTime.now();
        LocalDateTime startTime;
        switch (timeRange) {
            case "week":
                startTime = endTime.minusWeeks(1);
                break;
            case "month":
                startTime = endTime.minusMonths(1);
                break;
            case "year":
                startTime = endTime.minusYears(1);
                break;
            default:
                startTime = endTime.minusDays(1);
        }
        
        List<SoilData> dataList = soilDataRepository.findByDeviceIdAndCollectTimeBetweenOrderByCollectTimeDesc(
            deviceId, startTime, endTime);
        
        if (limit != null && limit > 0) {
            dataList = dataList.stream().limit(limit).collect(Collectors.toList());
        }
        
        return dataList.stream()
            .map(data -> convertToSensorDTO(data, deviceId))
            .collect(Collectors.toList());
    }

    /**
     * 获取图表数据
     */
    public ChartDataDTO getChartData(Long deviceId, Integer limit) {
        List<SoilData> dataList = soilDataRepository.findByDeviceIdOrderByCollectTimeDesc(deviceId);
        
        if (dataList.isEmpty()) {
            ChartDataDTO emptyChart = new ChartDataDTO();
            emptyChart.setTimeLabels(Collections.emptyList());
            emptyChart.setTemperature(Collections.emptyList());
            emptyChart.setHumidity(Collections.emptyList());
            emptyChart.setNitrogen(Collections.emptyList());
            emptyChart.setPhosphorus(Collections.emptyList());
            emptyChart.setPotassium(Collections.emptyList());
            emptyChart.setCo2(Collections.emptyList());
            emptyChart.setLightIntensity(Collections.emptyList());
            return emptyChart;
        }
        
        if (limit != null && limit > 0) {
            dataList = dataList.stream().limit(limit).collect(Collectors.toList());
        }
        
        // 反转列表以使数据按时间正序排列
        Collections.reverse(dataList);
        
        ChartDataDTO chartData = new ChartDataDTO();
        
        // 处理空值情况
        chartData.setTimeLabels(
            dataList.stream()
                .map(data -> data.getCollectTime().format(DateTimeFormatter.ofPattern("HH:mm")))
                .collect(Collectors.toList())
        );
        
        // 使用Optional处理可能的空值
        chartData.setTemperature(
            dataList.stream()
                .map(data -> Optional.ofNullable(data.getSoilTemperature()).orElse(0.0))
                .collect(Collectors.toList())
        );
        
        chartData.setHumidity(
            dataList.stream()
                .map(data -> Optional.ofNullable(data.getSoilMoisture()).orElse(0.0))
                .collect(Collectors.toList())
        );
        
        chartData.setNitrogen(
            dataList.stream()
                .map(data -> Optional.ofNullable(data.getNitrogen()).orElse(0.0))
                .collect(Collectors.toList())
        );
        
        chartData.setPhosphorus(
            dataList.stream()
                .map(data -> Optional.ofNullable(data.getPhosphorus()).orElse(0.0))
                .collect(Collectors.toList())
        );
        
        chartData.setPotassium(
            dataList.stream()
                .map(data -> Optional.ofNullable(data.getPotassium()).orElse(0.0))
                .collect(Collectors.toList())
        );
        
        chartData.setCo2(
            dataList.stream()
                .map(data -> Optional.ofNullable(data.getCo2()).orElse(0.0))
                .collect(Collectors.toList())
        );
        
        chartData.setLightIntensity(
            dataList.stream()
                .map(data -> Optional.ofNullable(data.getLightIntensity()).orElse(0.0))
                .collect(Collectors.toList())
        );
        
        chartData.setAirTemperature(
            dataList.stream()
                .map(data -> Optional.ofNullable(data.getAirTemperature()).orElse(0.0))
                .collect(Collectors.toList())
        );
        
        chartData.setAirHumidity(
            dataList.stream()
                .map(data -> Optional.ofNullable(data.getAirHumidity()).orElse(0.0))
                .collect(Collectors.toList())
        );
        
        return chartData;
    }

    /**
     * 将SoilData转换为SensorDataDTO
     */
    private SensorDataDTO convertToSensorDTO(SoilData data, Long deviceId) {
        SensorDataDTO dto = new SensorDataDTO();
        dto.setDeviceId(deviceId);
        dto.setCollectTime(data.getCollectTime());
        dto.setNitrogen(new SensorDataDTO.DataPoint(BigDecimal.valueOf(Optional.ofNullable(data.getNitrogen()).orElse(0.0)), "mg/kg", "氮含量"));
        dto.setPhosphorus(new SensorDataDTO.DataPoint(BigDecimal.valueOf(Optional.ofNullable(data.getPhosphorus()).orElse(0.0)), "mg/kg", "磷含量"));
        dto.setPotassium(new SensorDataDTO.DataPoint(BigDecimal.valueOf(Optional.ofNullable(data.getPotassium()).orElse(0.0)), "mg/kg", "钾含量"));
        dto.setSoilTemperature(new SensorDataDTO.DataPoint(BigDecimal.valueOf(Optional.ofNullable(data.getSoilTemperature()).orElse(0.0)), "℃", "土壤温度"));
        dto.setSoilMoisture(new SensorDataDTO.DataPoint(BigDecimal.valueOf(Optional.ofNullable(data.getSoilMoisture()).orElse(0.0)), "%", "土壤湿度"));
        dto.setConductivity(new SensorDataDTO.DataPoint(BigDecimal.valueOf(Optional.ofNullable(data.getConductivity()).orElse(0.0)), "μS/cm", "电导率"));
        dto.setPhValue(new SensorDataDTO.DataPoint(BigDecimal.valueOf(Optional.ofNullable(data.getPhValue()).orElse(0.0)), "", "pH值"));
        dto.setLightIntensity(new SensorDataDTO.DataPoint(BigDecimal.valueOf(Optional.ofNullable(data.getLightIntensity()).orElse(0.0)), "lux", "光照度"));
        dto.setCo2(new SensorDataDTO.DataPoint(BigDecimal.valueOf(Optional.ofNullable(data.getCo2()).orElse(0.0)), "ppm", "CO2浓度"));
        dto.setAirTemperature(new SensorDataDTO.DataPoint(BigDecimal.valueOf(Optional.ofNullable(data.getAirTemperature()).orElse(0.0)), "℃", "空气温度"));
        dto.setAirHumidity(new SensorDataDTO.DataPoint(BigDecimal.valueOf(Optional.ofNullable(data.getAirHumidity()).orElse(0.0)), "%", "空气湿度"));
        return dto;
    }

    private DeviceDTO convertToDTO(Device device) {
        DeviceDTO dto = new DeviceDTO();
        dto.setId(device.getId());
        dto.setDeviceName(device.getDeviceName());
        dto.setDeviceTypeId(device.getDeviceType().getId());
        dto.setDeviceTypeName(device.getDeviceType().getTypeName());
        dto.setStatus(device.getStatus());
        dto.setCreateTime(device.getCreateTime());
        dto.setUpdateTime(device.getUpdateTime());
        if (device.getDeviceType().getId() == 2) {
            List<CameraRecord> records = cameraRecordRepository.findByDeviceIdOrderByRecordTimeDesc(device.getId());
            if (!records.isEmpty()) {
                dto.setVideoUrl(records.get(0).getVideoUrl());
                dto.setThumbnailUrl(records.get(0).getThumbnailUrl());
            }
        }
        return dto;
    }
} 